<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // new 运算符
        // new运算符介绍
        // new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
        // 描述

        // 创建一个空的简单JavaScript对象（即{}）；
        // 链接该对象（设置该对象的constructor）到另一个对象 ；
        // 将步骤1新创建的对象作为this的上下文 ；
        // 如果该函数没有返回对象，则返回this。
        // 根据上面MDN中描述的效果不难看，其简单的运行过程是下面这个样子的：
        var People = function (name, age) {
            // 创建一个对象  this = {}  
            // 给当前this指向的对象赋值构造属性
            this.name = name
            this.age = age
            // return this  如果没有手动返回，则默认返回this指向的对象 
        }
        var person = new People('ceshi', 200)
        console.log(31, person);


        // 下面来看一下真正的new运算符实现的效果
        // 示例
        // 从上面的示例中可以看出，实例person可以访问People构造函数的属性name和age， 也可以访问到原型中的属性。了解了这些特点后，接下来我们开始模拟一个简单的new方法吧！
        // 由于我们自己模拟实现的new运算符方法无法像上面讲过的几种方法一样直接覆盖，所以这里面实现的是一个函数，用来模拟new运算符, 实现的思路如下：
        // 根据构造器的prototyp属性为原型，创建一个对象
        // 使用call或者apply方法，将this和调用参数传给构造函数执行
        // 如果构造器没有手动返回对象，则默认返回第一步创建的对象

        function People(name, age) {
            this.name = name
            this.age = age
        }

        People.prototype.sayHello = function () {
            console.log(`你好 ${this.name} !`)
        }

        var person = new People('hunter', 18)

        console.log(person.name, person.age) // hunter 18
        person.sayHello() // 你好 hunter !

        // 模拟实现new方法代码最终版
        var simulateNew = function (Parent, ...args) {
            // 创建对象，使其具有构造函数原型上面的属性
            var child = Object.create(Parent.prototype)
            // 使用 apply，改变构造函数 this 的指向到新建的对象，这样 child 就可以访问到构造函数中的属性
            var result = Parent.apply(child, args)
            // 判断是否有手动返回对象，没有则默认返回child
            return typeof result === 'object' ? result || child : child
        }
        //事列
        function car(num, type) {
            this.num = num
            this.type = type
        }
        let public = simulateNew(car, '123', '大众')
        console.log(69,public);
        
    </script>
</body>

</html>